﻿#include "LuaTable.h"
#include "LuaObjectImpl.h"


LuaTable::LuaTable()
{

}

LuaTable::LuaTable(LuaState* L)
	:LuaObject(L)
{
	
}

LuaTable::LuaTable(LuaObjectImpl* impl)
	:LuaObject(impl)
{
	
}

LuaTable::LuaTable(const LuaObject& rfs)
	:LuaObject(rfs)
{
}

LuaTable::LuaTable(const LuaTable& rfs)
	:LuaObject(rfs)
{
}


bool LuaTable::isValid() const
{
	return getType()==LUA_TTABLE;
}

LuaObject LuaTable::getTable(const char* key)
{
	if (isValid()) {
		LuaState* L = m_ptr->getCppLuaState();
		lua_pushstring(L->getLuaState(), key);
		lua_gettable(L->getLuaState(), m_ptr->getIndex());
		return LuaObject(L, -1);
	} else {
		return luaNil;
	}
}

LuaObject LuaTable::getTable(const std::string& key)
{
	if (isValid()) {
		LuaState* L = m_ptr->getCppLuaState();
		lua_pushlstring(L->getLuaState(), key.data(),key.length());
		lua_gettable(L->getLuaState(), m_ptr->getIndex());
		return LuaObject(L, -1);
	} else {
		return luaNil;
	}
}

LuaObject LuaTable::getTable(lua_Integer key)
{
	if (isValid()) {
		LuaState* L = m_ptr->getCppLuaState();
		lua_pushinteger(L->getLuaState(), key);
		lua_gettable(L->getLuaState(), m_ptr->getIndex());
		return LuaObject(L, -1);
	}
	else {
		return luaNil;
	}
}

LuaObject LuaTable::getTable(void* key)
{
	if (isValid()) {
		LuaState* L = m_ptr->getCppLuaState();
		lua_pushlightuserdata(L->getLuaState(), key);
		lua_gettable(L->getLuaState(), m_ptr->getIndex());
		return LuaObject(L, -1);
	}
	else {
		return luaNil;
	}
}


LuaObject LuaTable::rawGetTable(const char* key)
{
	if (isValid()) {
		LuaState* L = m_ptr->getCppLuaState();
		lua_pushstring(L->getLuaState(), key);
		lua_rawget(L->getLuaState(), m_ptr->getIndex());
		return LuaObject(L, -1);
	} else {
		return luaNil;
	}
}

LuaObject LuaTable::rawGetTable(const std::string& key)
{
	if (isValid()) {
		LuaState* L = m_ptr->getCppLuaState();
		lua_pushlstring(L->getLuaState(), key.data(),key.length());
		lua_rawget(L->getLuaState(), m_ptr->getIndex());
		return LuaObject(L, -1);
	} else {
		return luaNil;
	}
}

LuaObject LuaTable::rawGetTable(lua_Integer key)
{
	if (isValid()) {
		LuaState* L = m_ptr->getCppLuaState();
		lua_rawgeti(L->getLuaState(), m_ptr->getIndex(), key);
		return LuaObject(L, -1);
	} else {
		return luaNil;
	}
}

LuaObject LuaTable::rawGetTable(void* key)
{
	if (isValid()) {
		LuaState* L = m_ptr->getCppLuaState();
		lua_pushlightuserdata(L->getLuaState(), key);
		lua_rawget(L->getLuaState(), m_ptr->getIndex());
		return LuaObject(L, -1);
	}
	else {
		return luaNil;
	}
}


bool LuaTable::setTable(const char* key,LuaObject val)
{
	if(isValid())
	{
		lua_State* L=m_ptr->getLuaState();
		lua_pushstring(L,key);//key
		if(val.isNone())
			lua_pushnil(L);
		else
			lua_pushvalue(L,val.getIndex());//value
		lua_settable(L,getIndex());
		return true;
	}
	return false;
}

bool LuaTable::setTable(void* key, LuaObject val)
{
	if (isValid())
	{
		lua_State* L = m_ptr->getLuaState();
		lua_pushlightuserdata(L,key);//key
		if (val.isNone())
			lua_pushnil(L);
		else
			lua_pushvalue(L, val.getIndex());//value
		lua_settable(L, getIndex());
		return true;
	}
	return false;
}

bool LuaTable::setTable(lua_Integer key,LuaObject val)
{
	if(isValid())
	{
		lua_State* L=m_ptr->getLuaState();
		lua_pushinteger(L,key);//key
		if(val.isNone())
			lua_pushnil(L);
		else
			lua_pushvalue(L,val.getIndex());//value
		lua_settable(L,getIndex());
		return true;
	}
	return false;
}



bool LuaTable::rawSetTable(const char* key, LuaObject val)
{
	if (isValid())
	{
		lua_State* L = m_ptr->getLuaState();
		lua_pushstring(L, key);//key
		if (val.isNone())
			lua_pushnil(L);
		else
			lua_pushvalue(L, val.getIndex());//value
		lua_rawset(L, getIndex());
		return true;
	}
	return false;
}

bool LuaTable::rawSetTable(void* key, LuaObject val)
{
	if (isValid())
	{
		lua_State* L = m_ptr->getLuaState();
		lua_pushlightuserdata(L, key);//key
		if (val.isNone())
			lua_pushnil(L);
		else
			lua_pushvalue(L, val.getIndex());//value
		lua_rawset(L, getIndex());
		return true;
	}
	return false;
}

bool LuaTable::rawSetTable(lua_Integer key, LuaObject val)
{
	if (isValid())
	{
		lua_State* L = m_ptr->getLuaState();
		lua_pushinteger(L, key);//key
		if (val.isNone())
			lua_pushnil(L);
		else
			lua_pushvalue(L, val.getIndex());//value
		lua_rawset(L, getIndex());
		return true;
	}
	return false;
}

bool LuaTable::setConst(LuaConstDef* tag)
{
	if (!tag || !isValid())
		return false;

	lua_State* L = m_ptr->getLuaState();

	for (const LuaConstDef* c = &tag[0]; c->name; ++c) {
		lua_pushstring(L, c->name);
		lua_pushinteger(L, c->code);
		lua_rawset(L, getIndex());
	}
	return true;
}


//////////////////////////////////////////////////////////////////////////////////////////////////

LuaObject LuaTable::ArrayIterator::value() {
	return LuaTable(m_table)[m_index];
}

LuaTable::ArrayIterator LuaTable::arrayBegin() {
	return ArrayIterator(*this, 1);
}

LuaTable::ArrayIterator LuaTable::arrayEnd() {
	return ArrayIterator(*this, objLen() + 1);
}

LuaTable::Iterator::Iterator()
	:m_valid(false)
{
}


LuaTable::Iterator::Iterator(LuaObject ltab)
	:m_table(ltab),m_valid(false)
{
	assert (m_table.isTable());
	if(m_table.isTable())
	{
		lua_State* L=ltab.getLuaState();
		lua_pushnil(L);
		if(lua_next(L,m_table.getIndex()))
		{
			m_valid=true;
			m_key=LuaObject(ltab.getCppLuaState(), -2);
			m_value=LuaObject(ltab.getCppLuaState(),-1);
		}
	}
}

bool LuaTable::Iterator::operator++()
{
	if(m_table.isTable())
	{
		lua_State* L=m_table.getLuaState();
		lua_pushvalue(L,m_key.getIndex());
		if(lua_next(L,m_table.getIndex())!=0)
		{
			m_key=LuaObject(m_table.getCppLuaState(), -2);
			m_value=LuaObject(m_table.getCppLuaState(),-1);
			m_valid=true;
			return true;
		}
	}
	m_valid=false;
	return false;
}

bool LuaTable::Iterator::operator==(const Iterator& rfs)
{
	if (m_valid==rfs.isValid())
	{
		if (m_valid)
		{
			return m_key==rfs.m_key;
		}
		else
			return true;
	}
	else
		return false;
}


bool LuaTable::Iterator::operator!=(const Iterator& rfs)
{
	return !operator==(rfs);
}

bool LuaTable::Iterator::isValid()const
{
	return m_valid;
}


LuaTable::Iterator LuaTable::begin()
{
	return Iterator(*this);
}

LuaTable::Iterator LuaTable::end()
{
	return Iterator();
}



















